package cn.tedu.reflection;/**
 * @Author 金帮嘉诚 @Date 2021-06-25 星期五 9:40
 */
/*本类用于测试*/

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;

/**
 * 知识点
 * 获取 类对象
 * 通过类对象来获取 公共的：
 * 构造方法
 * 成员方法
 * 成员变量
 * 创建对象
 */
//类对象
public class TestReflect1 {
    //    @Test
//    public void getClazz() throws ClassNotFoundException {
//    Class.forName("")
//    类名.class
//    对象.getClass()
//        Class<?> student1 = Class.forName("cn.tedu.reflection.Student");
//        Class<Student> student2 = Student.class;
//        Class<?> student3 = new Student().getClass();
////getName()
    //getPackage().getName()
    //getSimpleName()
//        System.out.println(student1.getName());
//        System.out.println(student1.getPackage().getName());
//        System.out.println(student1.getSimpleName());
//    }


//构造方法
//    @Test
//    public void getConstruct() {
//        Class<Student> student1 = Student.class;
    //getConstructors()
//        Constructor<?>[] cs = student1.getConstructors();
//        for (Constructor c : cs
//        ) {
//            System.out.println(c.getName());
    //getParameterTypes()
//            Class[] parameterTypes = c.getParameterTypes();
//            System.out.println(Arrays.toString(parameterTypes));
//        }
//    }


//成员方法
//    @Test
//    public void getFunction() throws Exception {
//        Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
//        //getMethods()
//        Method[] m1 = clazz.getMethods();
//
//        for (Method m : m1
//        ) {
//            System.out.print(m.getName());
//            //getParameterTypes
//            Class<?>[] parameterTypes = m.getParameterTypes();
//            System.out.println(Arrays.toString(parameterTypes));
//        }
//
//    }


//成员变量
//    @Test
//    public void getFields(){
//        Class<?> clazz = Student.class;
//        //getFields()
//        Field[] cF = clazz.getFields();
//        //2.获取所有的成员变量,公共的!!!
//        /*!!!注意目前成员变量的修饰符必须是public才能获取到,采用默认修饰符就反射不到*/
////        /*注意目前成员变量得修饰符必须是public才能获取到，采用默认修饰符就反射不到*/
//        System.out.println("???");
//        for (Field f:cF
//             ) {
//            //把变量name设置成public的结果
//            System.out.println(f.getName());//name
//            //getType()
//            Class<?> type = f.getType();
//            System.out.println(type);//class java.lang.String
//            System.out.println(type.getName());//java.lang.String
//        }
//    }


    //创建对象
    /*方式一：通过字节码对象直接调用newInstance()方法触发无参构造来创建对象
    方式二：先获取指定的构造函数，再通过这个构造函数对象来创建对象
     * 方式二：先获取指定的构造函数，再通过构造函数对象调用newInstance()方法调用对应构造函数创建对象*/
    @Test
    public void getObject() throws Exception {
        Class<?> clazz = Student.class;
        //方式一：通过字节码对象直接调用newInstance()触发无参构造
//        Student st1=clazz.newInstance();//不行
        /*会触发无参构造*/
        Object obj1 = clazz.newInstance();//此步newInstance()抛出异常
        //重写toString()才能输出Student{name='null', age=0}
        //否则打印的是对象的地址值
        System.out.println(obj1);

//        Constructor<?>[] constructors = clazz.getConstructors();
//        for (Constructor c:constructors
//             ) {
//            Class[] parameterTypes = c.getParameterTypes();
//            System.out.println(Arrays.toString(parameterTypes));
//        }

        //方式二：
        //1.用字节码对象调用getConstructor(参数.class列表)
        //2.用有参构造函数对象调用newInstance(设置参数)创建Object对象
        //3.强制类型转换为Student类对象

        //获取指定构造方法
        /*注意！！这个方法 参数类型 是 构造方法参数类型对应的字节码对象 */
        Constructor<?> c1 = clazz.getConstructor(String.class, int.class);
        Object obj2 = c1.newInstance("胡坦", 1);
        System.out.println(obj2);

        //通过 反射创建的对象 获取属性值 使用方法
        /*注意！此处需要把父类型Object类型的obj强制转换成子类型Student的s
         * 为什么要强转？因为此处我们想要使用子类的特有功能，而父类无法使用子类的特有功能
         * Object父类中是没有Student子类的自己的属性和功能的
         * 所以，我们把之前看作是父类型的子类对象转回成子类型，去调用子类的特有功能
         *
         * 这个现象称为：子类的向下造型【注意向下之前必须先向上造型，纯粹的父类对象不能向下造型】*/
        //向下造型：因为 想使用 子类特有功能
        Student student = (Student) obj2;
//        Object obj3=student;
//        Student student2 = (Student) obj3;
//        System.out.println(student2.name);
        System.out.println(student.name);
        System.out.println(student.age);
        student.eat();
        student.play(1);
    }
}
